var gameAllData={0:{'gameKey':{0:{score:0}}},1:{}};
var recordData={'gameKey':{0:{score:0}}};
var homeData={0:{score:0}};
var gameData={score:0};
var gameColors=['#845EC2','#D65DB1','#FF6F91','#FF9671','#CD6155','#C0392B','#A93226','#922B21','#B03A2E','#CB4335','#E74C3C','#EC7063','#AF7AC5','#9B59B6','#884EA0','#76448A','#0081CF','#2C73D2','#008E9B']
var gameSounds=['C4','D4','E4','F4','G4','A4','B4','C5','D5','E5','F5','G5','A5','B5','C6','D6','E6','F6','G6','A6','B6'];
const PY_URL='https://ywx620.gitee.io/learn/rec/sound/pinyin/all/$num.mp3';//拼音
const CY_URL='https://ywx620.gitee.io/learn/rec/sound/ciyu/$num.mp3';//词语
const MAINGAMEKEY='mainGameKey';
const RECORD='record-'
/***
 * 需要的类库
  	<script src="../libs/Unify.js"></script>
	<script src='../libs/easeljs.js'></script>
	<script src="../libs/createui.js"></script>
	<script src="../libs/createEvent.js"></script>
    <script src="../libs/createSprite.js"></script>
	<script src="../libs/createGame.js"></script>
	<script src="../libs/Tone.js"></script>
	<script src="../libs/SoundFactory.js"></script>
	<script src="../libs/PinyinFactory.js"></script>
	<script src="../libs/ColorManager.js"></script>
 */
class BasicClass extends MBasice{
    constructor() {
        super();
        mColor.colorNormal = '#ED9554';
		mColor.colorOver = '#FFC03C';
		mColor.colorDown = '#E8741E';
        this.userNames=['乐乐存档','恩恩存档','文文存档','娜娜存档','铭铭存档','欣欣存档'];
        this.width=Unify.getStageWH().w;
        this.height=Unify.getStageWH().h;
        this.minNum=9;
        if(Unify.isMobile()){
            this.wid=this.width/this.minNum;
        }else{
            this.wid=this.height/18;
        }
        this.midWin=this.wid*this.minNum;
        this.leftX=(this.width-this.wid*this.minNum)/2;
        this.centerPos={x:this.width/2,y:this.height/2};
        this.oneInput=true;
        this.isLoop=true;
        this.onLoop();
        this.initStart();
    }
    initStart(){//子类中去调用
    }
    initScene(){
        console.log('initScene')
        this.createScene({});
        this.createBtnClose();
		this.createStarMoonSun();
		this.createRecordButton();
        this.initSceneNext();
    }
    initData(keyName){
        console.log('initData')
        if(!keyName) console.warn("keyName为空时不做本地数据保存");
        this.keyName=keyName;
        //Unify.localStorage('remove',this.keyName);
        if(MAINGAMEKEY==keyName){
            let gameData=Unify.localStorage('get',this.keyName)||'{}';
            gameData=JSON.parse(gameData);
            gameAllData=gameData;
        }
    }
    createScene({c1='#F3C099',c2='#F3C099',c3='#F3C099'}) {
        this.sceneLayer=new MBasice();
        this.topLayer=new MBasice();
        this.sceneRecord = new MScene({color:c1});
		this.sceneHome = new MScene({color:c2});
        this.sceneGame = new MScene({color:c3});
        this.scenes=[this.sceneRecord,this.sceneHome,this.sceneGame];
        this.addChild(this.sceneLayer);
        this.addChild(this.topLayer);
        this.enterRecord();
        this.createRightWrongIcon();
    }
    createRightWrongIcon(){
        this.iconRight=new MLabel({label:'✔️'});
        this.iconWrong=new MLabel({label:'❌'});
        let icons=[this.iconRight,this.iconWrong];
        icons.forEach((icon)=>{
            icon.setPos(this.centerPos.x,this.centerPos.y);
            icon.scale=icon.alpha=0;
            this.topLayer.addChild(icon);
        })
    }
    initSceneNext(){

    }
    removeScene(){
        this.scenes.forEach((scene)=>{
            scene.removeFromParent();
        })
    }
    enterRecord(){
        this.removeScene();
        this.sceneLayer.addChild(this.sceneRecord);
        this.enterRecordNext();
    }
    enterHome(){
        this.removeScene();
        this.sceneLayer.addChild(this.sceneHome);
        this.enterHomeNext();
    }
    enterGame(){
        this.removeScene();
        this.sceneLayer.addChild(this.sceneGame);
        this.enterGameNext();
    }
    enterRecordNext(){}
    enterHomeNext(){}
    enterGameNext(){}
    createRecordButton(){
        let btns=[];
        let [w,h]=[0,0];
        let len=6;
        for(let i=0;i<len;i++){
            let j=i+1;
            let btn=new MButton({label:`空存档${j}`,width:this.wid*6,height:this.wid});
            btn.index=i;
            let name=RECORD+i;
            if(gameAllData){
                if(!gameAllData[name])gameAllData[name]={};
                recordData=gameAllData[name];
                let time=recordData.time||0;
                console.log('time=',time)
                if(time>0){
                    btn.setText(`${this.userNames[i]} ${Unify.dateFormat('YY/MM/DD',new Date(time))}`)
                }
            }
            btn.on('click',(e)=>{
                this.indexRecord=e.currentTarget.index;
                let name=RECORD+this.indexRecord;
                if(!gameAllData[name])gameAllData[name]={};
                recordData=gameAllData[name];
                console.log(recordData,gameAllData)
                this.playSoundByCode();
                this.enterHome();
            });
            this.sceneRecord.addChild(btn);
            w=btn.width;h=btn.height;
            btns.push(btn);
        }
        let x=(this.width-w)/2;
        let y=(this.height-(h+10)*len)/2;
        Unify.displayRank(btns,1,10,10,x,y);
    }
    createHomeButton(names,num=1){
        let btns=[];
        let [w,h]=[0,0];
        let len=names.length;
        for(let i=0;i<len;i++){
            let btn=new MButton({label:names[i],width:this.wid*6/num,height:this.wid});
            btn.index=i;
            btn.on('click',(e)=>{
                this.selectNum=e.currentTarget.index;
                this.setHomeData();
                this.playSoundByCode();
                this.enterGame();
            });
            this.sceneHome.addChild(btn);
            w=btn.width;h=btn.height;
            btns.push(btn);
        }
        let x=(this.width-w)/2/num;
        let y=(this.height-(h+10)*len)/2*num;
        Unify.displayRank(btns,num,10,10,x,y);
    }
    setHomeData(){

    }
    createNumKey(names,g=10,n=2,offy=0,ww){
        names=names||['0','1','2','3','4','5','6','7','8','9','cl','ok'];
        let num=Math.floor(names.length/n);
        let w=ww||this.wid;
        let btns=[];
        for(let i=0;i<names.length;i++){
            let btn=new MButton({label:names[i],width:w,height:w});
            btn.code=names[i];
            btn.on('click',this.onKeyboard,this);
            this.sceneGame.addChild(btn);
            btns.push(btn);
        }
        let x=(this.width-(w+g)*num)/2+g/2;
        let y=(this.height-w*2.5)+offy;
        Unify.displayRank(btns,num,g,g,x,y);
    }
    onKeyboard(e){
        let code=e.currentTarget.code;
        this.playSoundByCode();
        console.log(code);
        if(this.input){
            switch(code){
                case 'ok':
                    this.judge();
                    break;
                case 'cl':
                    this.input.value='';
                    break;
                default:
                    this.onInput(code);
                    break;
            }
        }
    }
    onInput(code){
        if(this.oneInput)   this.input.value=code;
        else                this.input.value+=code;
    }
    judge(){
        //子类实现
    }
    createStarMoonSun(){
        var sprite=new MSprite();
        let [w,n]=[this.wid,this.minNum];
        let [sw,sh,r]=[w*n*0.98,w*n/3,w/3];
        let color='yellow';
		sprite.drr(sw,sh,5,'#DAAB83',{s:2,c:'#AC7A59'});
		sprite.setPos((this.width-sw)/2,5);
		this.sceneGame.addChild(sprite);
        sprite.stars=[];
        for(let i=0;i<5;i++){
            let star=new MSprite();
            star.dps(r,5,2,color);
            sprite.addChild(star);
            star.alpha=0.1;
            sprite.stars.push(star);
        }
        let g=w/4;
        let [x,y]=[(sw-(r*2+g)*5)/2+g+5,sh-w*0.5]
        Unify.displayRank(sprite.stars,5,g,g,x,y);
        var moon=new MShape();
        moon.dm(1,r,color)
        moon.setPos(w*2,w/2);
		sprite.addChild(moon);
        var sun=new MShape();
        sun.dc(r,color);
        sun.setPos(sw-w*2,w/2);
		sprite.addChild(sun);
        for(let i=0;i<5;i++){
            let label=new MLabel({label:''});
            sprite.addChild(label);
            if(i==0)      sprite.txtStar=label;
            else if(i==1) sprite.txtMoon=label;
            else if(i==2) sprite.txtSun=label;
            else if(i==3) sprite.txtModel=label;
            else if(i==4) sprite.txtInput=label;
        }
        sprite.txtMoon.setPos(moon.x-w,moon.y);
        sprite.txtSun.setPos(sun.x-w,sun.y);
        sprite.txtInput.setPos(sw/2,sh/2);
        sprite.txtModel.setPos(w,y);
        sprite.txtStar.setPos(sw-w,y);
        this.topToolBar=sprite;
    }
    createBtnClose(){
        let btn=new MCircleButton({label:'X',radius:this.wid*0.4});
        btn.y=this.wid*0.2;
        btn.x=this.width-this.wid*1.2;
        btn.on('click',this.onClose,this);
        this.topLayer.addChild(btn);
    }
    onClose(){
        this.playSoundByCode('B4');
        if(this.sceneGame.parent)this.enterHome();
        else if(this.sceneHome.parent)this.enterRecord();
    }
    onLoop(){
        if(this.isLoop){
            this.loopTime=new Date().getTime();
            setTimeout(()=>{
                this.update(new Date().getTime()-this.loopTime);
                this.onLoop();
            },16.666);
        }
    }
    addCover(t=0,a=0.2){
        this.removeCover();
        if(!this.cover){
            this.cover=new MSprite();
            this.cover.dr(this.width,this.height,'black');
            this.cover.on('click',(e)=>{e.stopPropagation()});//停止事件传传播
            this.cover.alpha=a;
        }
        this.addChild(this.cover);
        if(t>0){
            setTimeout(()=>{this.removeCover()},t);
        }
    }
    removeCover(){
        if(this.cover){
            this.cover.removeFromParent();
        }
    }
    destroy(){
        this.isLoop=false;
        this.sceneRecord.removeFromParent(true);
		this.sceneHome.removeFromParent(true);
        this.sceneGame.removeFromParent(true);
        this.sceneLayer.removeFromParent(true);
        this.topLayer.removeFromParent(true);
        this.scenes=null;
        this.sceneRecord=null;
		this.sceneHome=null;
        this.sceneGame=null;
        this.sceneLayer=null;
        this.topLayer=null;
    }
    playSoundByCode(code='C4',time='16n'){
        try{
            if(!this.synth)this.synth = new Tone.PolySynth(Tone.Synth).toDestination();
            this.synth.triggerAttackRelease(code, time);
        }catch(e){
            console.log('未加载Tone类');
        }
    }
    playSoundByIndex(index){
        if(index<0||index>gameSounds.length-1)index=Math.floor(Math.random()*gameSounds.length);
        this.playSoundByCode(gameSounds[index]);
    }
    showIconAnimation(icon){
        icon.scale=icon.alpha=0;
        MTween.set(icon).go(200,{scale:3,alpha:1}).go(300).go(50,{scale:0,alpha:0}).start();
    }
    playSoundRight(){
        setTimeout(this.playSoundByCode('C6'),500);
        this.showIconAnimation(this.iconRight); 
    }
    playSoundWrong(){
        setTimeout(this.playSoundByCode('C2'),500);
        this.showIconAnimation(this.iconWrong);
    }
    /**显示分数*/
    showScore(){
        let cnt=this.gameData.score||0;
        let sun=Math.floor(cnt/25);
        let mo=cnt%25;
        let moon=Math.floor(mo/5);
        let star=mo%5;
        let stars=this.topToolBar.stars;
        this.alphas(stars);
        this.alphas(stars,0,star,1);
        this.topToolBar.txtSun.value=String(sun);
        this.topToolBar.txtMoon.value=String(moon);
        this.topToolBar.txtStar.value=String(cnt)+'星';
        this.topToolBar.txtModel.value='模式'+Number(this.selectNum+1);
        this.saveData();
    }
    addScore(s=1){
        this.gameData.score+=s;
        this.showScore();
    }
    /**保存数据*/
    saveData(){
        recordData.time=(new Date).getTime();
        //console.log(homeData)
        Unify.localStorage('set',MAINGAMEKEY,JSON.stringify(gameAllData));
    }
    /**取得本地的所有分数 */
    getLocalTotalScore(data){
        let score=0;
        function countScore(data){
            if(data.score>0){
                score+=data.score;
            }else{
                for(let i in data){
                    let da=data[i];
                    if(typeof(da)=='object'){
                        if(da.score>0){
                            score+=da.score;
                        }else{
                            countScore(da)
                        }
                    }
                }
            }
        }
        countScore(data)
        return score;
    }
    /**设置数组中的透明度*/
    alphas(nodes,s=0,e=-1,a=0.1){
        let len=nodes.length;
        if(e<0) e=len;
        else     e=e>len?len:e;
        if(s<0) s=0;
        else     s=s>len?len:s;
        for(let i=s;i<e;i++){
            let node=nodes[i];
            if(node) node.alpha=a;
        }
    }
    checkDistance(p1,p2,max){
        let [x,y]=[p1.x-p2.x,p1.y-p2.y];
        let dis=Math.sqrt(x*x+y*y);
        return dis<max;
    }
    update(dt){
        //console.log(dt);
    }
}
class MainGame extends BasicClass{
    initStart(){
        this.initData(MAINGAMEKEY);
        this.localData=gameAllData;
        this.initScene();
    }
    initScene(){
        console.log('initScene');
        this.initLabels();
        this.createScene({});
        this.createBtnClose();
		this.createRecordButton();
        this.createHomeButton(this.labels,2);
        this.initSceneNext();
        this.createTextStar();
    }
    createTextStar(){
        this.txtHomeStar=new MLabel({label:'',c:'yellow'});
        this.txtHomeStar.setPos(this.width/2,this.wid*0.6);
        this.sceneHome.addChild(this.txtHomeStar);
    }
    setHomeData(){
        let name=this.labels[this.selectNum];
        if(!recordData[name])recordData[name]={};
        homeData=recordData[name];
    }
    initLabels(){
        let labelClass={
            '拼音测试':PinyinTestGame,
            '拼音顺序1':PinyinOrderGame,
            '拼音顺序2':PinyinOrderGame2,
            '拼音顺序3':PinyinOrderGame3,
            '口算器':MouthCountGame,
            '列算式计算':ColumnCountGame,
            '数学题目':MathQuestion,
            '正方体的摆放':CubeFreeDrag,
            '变色小球':ColorBallGame,
            '变色方块':ColorBoxGame,
            '对对碰':ColorSupperzzleGame,
            '摩斯码':MorseCode,
            '自由输入':FreeInput,
        }
        this.labels=Object.keys(labelClass);
        this.classs=Object.values(labelClass);
    }
    enterHomeNext(){
        this.txtHomeStar.value='总星数：'+this.getLocalTotalScore(recordData);
    }
    enterGameNext(){
        this.game=new this.classs[this.selectNum];
        this.game.addEvent('close',this.closeGame.bind(this))
        this.addChild(this.game);
    }
    closeGame(){
        this.game.destroy();
        this.game=null;
        this.enterHome();
    }
}
/**基础游戏类 */
class BasicGame extends BasicClass{
    initScene(){
        this.createScene({});
        this.createStarMoonSun()
        this.createBtnClose();
        this.createHomeButton(this.getLabels());
        this.createTextStar();
        this.enterHome();
        this.initSceneNext();
    }
    createTextStar(){
        this.txtHomeStar=new MLabel({label:''});
        this.txtHomeStar.setPos(this.width/2,this.wid);
        this.sceneHome.addChild(this.txtHomeStar);
    }
    onClose(){
        this.playSoundByCode('B4');
        if(this.sceneGame.parent)this.enterHome();
        else if(this.sceneHome.parent){
            this.emitEvent('close');
        }
    }
    setHomeData(){
        let name=this.selectNum;
        if(!homeData[name])homeData[name]={score:0};
        gameData=homeData[name];
        this.gameData=gameData;
    }
    enterHomeNext(){
        this.txtHomeStar.value='总星数：'+this.getLocalTotalScore(homeData);
    }
    createDownTime(y=80){
        let shape=new MEmoji();
        let end=this.width-70;
		this.sceneGame.addChild(shape);
		shape.setPos(50,y)
		shape.drawEmoji('🚩');
		
		shape=new MSprite();
		this.sceneGame.addChild(shape);
		shape.setPos(40,y+35)
		shape.dr(end,4,'#666666');

		shape=new MEmoji();
		this.sceneGame.addChild(shape);
        shape.end=end+30;
		shape.setPos(shape.end,y)
		shape.drawEmoji('🚴🏼');
		this.bike=shape;
    }
    startDownTime(t=3,callBack){
        t=t*60*1000;
        this.bike.x=this.bike.end;
        MTween.set(this.bike,'to',callBack).go(t,{x:50}).start();
    }
    gameOver(){
        this.isPlay=false;
        MUtil.sureCancel(`游戏结束，获得${this.score} 分\n是否再玩一次？`, (type) => {
            if(type){
                this.enterGame();
            }else{
                this.enterHome();
            }
        })
    }
}
/**拼音测试*/
class PinyinTestGame extends BasicGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['自由练习','开始测试'];
    }
    initSceneNext(){  
        this.titles=[['sm'],['ym'],['ztrd']];
        const colors=ColorManager.warnCoolColors([2,3,5,8,11,10,11,9])
        const all=PinyinFactory.all();
        const labels=all.zw;
        let [x,y,xnum,wid,hei]=[2,10,8,0,0];
        wid=this.wid;
        hei=this.height/(xnum+8);
        x=(this.width-wid*xnum)/2;
        let oy=wid*3;
        let self=this;
        draw(all.sm,oy,0,0);
        draw(all.ym,oy+hei*4,1);
        draw(all.zt,oy+hei*8,2);
        draw(['再读一次'],oy+hei*11,3);
        function draw(arr,offy=0,t=0){
            let color=colors[t];
            let boxs=[];
            if(t==3){
                wid=wid*3;
            } 
            for(let i=0;i<arr.length;i++){
                let name=arr[i];
                let box=createButton(wid,hei,name,color);
                box.on('click',self.onClick,self);
                boxs.push(box);
            }
            let label=new MLabel({label:labels[t],c:'#059E11'});
            label.setLeft();
            self.sceneGame.addChild(label);
            [label.x,label.y]=[x+4,offy+hei/2-2]
            let [gx,gy]=[wid/xnum,hei/xnum]
            Unify.displayRank(boxs,xnum,gx,gy,x-gx*4+2,y+hei/2+offy);
            if(t==3){
                label.removeFromParent(true);
                let box=boxs[0];
                box.x=(self.width-box.width)/2;
                box.y=self.height-box.height-20;
                self.btnReplay=box;
            }
        }
        function createButton(w,h,label='文字',colorBg="#666666"){
            var btn=new MButton({label:label,width:w,height:h});
            btn.setSkinColors(colorBg,'green','blue');
            btn.name=label;
            self.sceneGame.addChild(btn);
            return btn;
        }
        this.all=all;
    }
    enterGameNext(){
        this.btnReplay.visible=this.selectNum
        this.showScore();
        if(this.selectNum==1){
            this.playTitle();
        }
    }
    onClick(e){
        let name=e.currentTarget.name;
        if(name){
            if(name=='再读一次'){
                this.replay();
            }else{
                this.playPy(name,1);
            }
        }
    }
    playPy(name,type){
        let url=PY_URL.replace('$num',name);
        SoundFactory.alone(url,()=>{
            if(this.selectNum==1){
                if(type){
                    if(name==this.selPy){
                        this.playRightWrong(1);
                    }else{
                        this.playRightWrong(0);
                    }
                }
            }
        });
    }
    replay(){
        this.playSound(this.titles[this.selNum])
    }
    next(){
        this.addScore();
        this.playTitle();
    }
    playTitle(){
        let selNum=Math.floor(Math.random()*3);
        let selPy=null;
        if(selNum==0){
            selPy=this.all.sm[Math.floor(Math.random()*this.all.sm.length)]
        }else if(selNum==1){
            selPy=this.all.ym[Math.floor(Math.random()*this.all.ym.length)]
        }else{
            selPy=this.all.zt[Math.floor(Math.random()*this.all.zt.length)]
        }
        console.log(selNum,selPy)
        this.selNum=selNum;
        this.selPy=selPy;
        this.playSound(this.titles[this.selNum])
    }
    playRightWrong(type){
        let arr=['clcl','ntbl']
        let url=CY_URL.replace('$num',arr[type]);
        SoundFactory.alone(url,()=>{
            if(type) this.next();
            else     this.wrongReplay();
        });
    }
    wrongReplay(){//错了再来一次
        this.replay();
    }
    playSound(arg){
        var urls=[];
        for(let i=0;i<arg.length;i++){
            let name=arg[i];
            let u=CY_URL.replace('$num',name);
            urls.push(u);
        }
        SoundFactory.array(urls,this.callBack.bind(this));
    }
    callBack(){
        console.log('播放完毕');
        this.playPy(this.selPy);
    }
}
/**拼音顺序选*/
class PinyinOrderGame extends PinyinTestGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['声母','韵母','整体认读'];
    }
    createBtnReplay(){
        let wid=this.wid;
        this.btnReplay=new MButton({label:'再读一次',width:wid*3,height:wid});
        this.btnReplay.on('click',this.replay,this);
        this.btnReplay.setSkinColors('#059E11','green','#559E11');
        this.btnReplay.x=(this.width-this.btnReplay.width)/2;
        this.btnReplay.y=this.height-wid*2;
        this.sceneGame.addChild(this.btnReplay);
    }
    createNodes(wid,n=4,s=2,c='white',r=10){
        this.createBtnReplay();
        this.nodes=[];
        for(let i=0;i<n;i++){
            let node=new MSprite();
            node.on('click',this.onClick,this);
            node.drr(wid,wid,r,c);
            node.createLabel('white');
            node.label.scale=s;
            node.label.value='zhong';
            this.sceneGame.addChild(node);
            this.nodes.push(node);
        }
    }
    initSceneNext(){  
        this.titles=[['sm'],['ym'],['ztrd']];
        this.colors=['#845EC2','#D65DB1','#FF6F91','#FF9671']//,'#0081CF','#2C73D2','#008E9B']
        let wid=this.wid*3;
        this.createNodes(wid);
        let n=2;
        let gap=this.wid/n;
        let [x,y]=[this.leftX,this.height/2-wid];
        x+=(this.midWin-(wid*n+gap*(n-1)))/2;
        Unify.displayRank(this.nodes,n,gap,gap,x,y);
        this.nodes.forEach(a=>a.alpha=0);
    }
    enterGameNext(){
        this.showScore();
        this.all=PinyinFactory.all()[this.titles[this.selectNum]];
        this.playTitle();
        //console.log(this.all);
    }
    onClick(e){
        let node=e.currentTarget;
        if(node.canClick){
            node.label.color='black';
            let [y1,y2]=[node.y+10,node.y];
            // MTween.timeLine([
			// 	[50,{type:'to',item:node,data:{y:y1},time:100}],
			// 	[50,{type:'to',item:node,data:{y:y2},time:100}]
			// ]);
            MTween.set(node).go(100,{y:y1}).go(60,{y:y2}).start();
            let name=node.label.value;
            let url=PY_URL.replace('$num',name);
            SoundFactory.only(url);
            //console.log(this.selPys,this.selIndex,name);
            if(this.selPys[this.selIndex]==name){
                this.selIndex++;
                if(this.selIndex==this.selPys.length){
                    setTimeout(()=>{this.playRightWrong(1);},500);  
                }
            }else{
                this.addCover();
                setTimeout(()=>{this.playRightWrong(0);},500);  
            }
        }
    }
    setNodeClick(boo){
        this.nodes.forEach((a)=>{
            a.canClick=boo;
            a.label.color='white';
        });
    }
    playTitle(){
        this.selPys=[];
        let len=this.nodes.length;
        while(this.selPys.length<len){
            let py=Unify.getArrayRandomValue(this.all);
            if(!this.selPys.includes(py)){
                this.selPys.push(py);
            }
        }
        console.log(this.selPys);
        let colors=Unify.getArrayRandomValue(this.colors,4);
        for(let i=0;i<len;i++){
            let node=this.nodes[i];
            node.label.value=this.selPys[i];
            node.color=colors[i];
            node.alpha=0;
            let y=node.y;
            node.y-=50;
            MTween.to(node,{alpha:1,y:y},500);
        }
        Unify.arrayRandomSort(this.selPys);
        this.replay();
    }
    replay(){
        this.selIndex=0;
        this.addCover();
        this.setNodeClick(false);
        this.playSound(this.titles[this.selectNum]);
    }
    callBack(){
        var urls=[];
        for(let i=0;i<this.selPys.length;i++){
            let name=this.selPys[i];
            let u=PY_URL.replace('$num',name);
            urls.push(u);
        }
        SoundFactory.array(urls,this.startAnswer.bind(this));
    }
    startAnswer(){
        this.setNodeClick(true);
        this.removeCover();
    }
}
/**拼音顺序选*/
class PinyinOrderGame2 extends PinyinOrderGame{
    initSceneNext(){  
        this.titles=[['sm'],['ym'],['ztrd']];
        this.colors=['#845EC2','#D65DB1','#FF6F91','#FF9671','#CD6155','#C0392B','#A93226','#922B21','#B03A2E','#CB4335','#E74C3C','#EC7063','#AF7AC5','#9B59B6','#884EA0','#76448A','#0081CF','#2C73D2','#008E9B']
        let wid=this.wid*2;
        this.total=16;
        this.createNodes(wid,this.total,1.5,'#845EC2',5);
        let n=4;
        let gap=this.wid/n;
        let [x,y]=[this.leftX,this.height/2-wid*1.5];
        x+=(this.midWin-(wid*n+gap*(n-1)))/2;
        Unify.displayRank(this.nodes,n,gap,gap,x,y);
    }
    enterGameNext(){
        this.count=3;
        this.showScore();
        this.all=PinyinFactory.all()[this.titles[this.selectNum]];
        this.playTitle();
    }
    getMaxCount(){
        let max=this.gameData.count||this.count;
        if(this.count>=max){
            this.gameData.count=this.count;
        }
        return this.gameData.count;
    }
    playTitle(){
        this.selPys=[];
        if(this.count>this.total){
            this.count=this.total;
        }
        let maxCount=this.getMaxCount();
        this.topToolBar.txtInput.value=`当前${this.count}个     最高${maxCount}个`;
        let len=this.count++;
        while(this.selPys.length<len){
            let py=Unify.getArrayRandomValue(this.all);
            if(!this.selPys.includes(py)){
                this.selPys.push(py);
            }
        }
        //let colors=Unify.getArrayRandomValue(this.colors,len);
        let color=Unify.getArrayRandomValue(this.colors);
        this.nodes.forEach(a=>a.alpha=0);
        Unify.arrayRandomSort(this.nodes);
        for(let i=0;i<len;i++){
            let node=this.nodes[i];
            node.label.value=this.selPys[i];
            node.color=color//colors[i];
            node.alpha=0;
            let y=node.y;
            node.y-=20;
            MTween.to(node,{alpha:1,y:y},500);
        }
        Unify.arrayRandomSort(this.selPys);
        console.log(this.selPys);
        this.replay();
    }
    wrongReplay(){//错了重新来过
        this.enterGameNext();
    }
}
/**拼音顺序选*/
class PinyinOrderGame3 extends PinyinOrderGame2{
    initSceneNext(){
        this.titles=[['sm'],['ym'],['ztrd']];
        this.colors=['#845EC2','#D65DB1','#FF6F91','#FF9671'];
        let wid=this.wid*3;
        this.createNodes(wid);
        this.total=16;
        this.nodes.forEach((node,index)=>{
            node.shape.setPos(-wid/2,-wid/2);
            node.label.x=node.label.y=0;
            node.color=this.colors[index];
            node.index=index;
        })
        let n=2;
        let gap=this.wid/n;
        let [x,y]=[this.leftX,this.height/2];
        x+=(this.midWin-(wid*n+gap*(n-1)))/2+wid/2;
        Unify.displayRank(this.nodes,n,gap,gap,x,y);
    }
    enterGameNext(){
        this.count=4;
        this.showScore();
        this.all=PinyinFactory.all()[this.titles[this.selectNum]];
        this.playTitle();
    }
    playTitle(){
        if(this.count>this.total){
            this.count=this.total;
        }
        let maxCount=this.getMaxCount();
        this.topToolBar.txtInput.value=`当前${this.count}个     最高${maxCount}个`;
        this.selPys=[];
        let len=4;
        while(this.selPys.length<len){
            let py=Unify.getArrayRandomValue(this.all);
            if(!this.selPys.includes(py)){
                this.selPys.push(py);
            }
        }
        this.indexs=[];
        while(this.indexs.length<this.count){
            this.indexs.push(Math.floor(Math.random()*len));
        }
        for(let i=0;i<len;i++){
            let node=this.nodes[i];
            node.label.value=this.selPys[i];
        }
        this.replay();
        this.count++;
    }
    callBack(){
        var [urls,cnt,self]=[[],0,this];
        for(let i=0;i<this.selPys.length;i++){
            let name=this.selPys[i];
            let u=PY_URL.replace('$num',name);
            urls.push(u);
        }
        function plaSou(){
            //console.log(cnt,self.indexs)
            if(cnt<self.indexs.length){
                let i=self.indexs[cnt++];
                self.playNode(self.nodes[i]);
                let url=urls[i];
                SoundFactory.only(url,plaSou);
            }else{
                self.startAnswer();
            }
        }
        plaSou();
    }
    playNode(node){
        MTween.set(node).go(200,{scale:0.6}).go(100,{scale:1}).start();
        MTween.set(node.label).go(300).go(100,{scale:3}).go(100,{scale:2}).start();
    }
    onClick(e){
        let node=e.currentTarget;
        this.playNode(node);
        let [name,index]=[node.label.value,node.index];
        let url=PY_URL.replace('$num',name);
        SoundFactory.only(url);
        if(this.indexs[this.selIndex]==index){
            this.selIndex++;
            if(this.selIndex==this.indexs.length){
                setTimeout(()=>{this.playRightWrong(1);},500);  
            }
        }else{
            setTimeout(()=>{this.playRightWrong(0);},500);  
        }
    }
}
/**口算器*/
class MouthCountGame extends BasicGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['个数加减','两位数加减','三位数加减','四位数加减','个位数乘法','整除计算','个位数与两位数乘法','两位数与两位数乘法'];
    }
    initSceneNext(){  
        this.createHomeButton(this.getLabels());
        let names=['0','1','2','3','4','5','6','7','8','9','cl','ok'];
        let wid=this.height/8;
        this.createNumKey(names,10,3,-wid,wid);
        this.oneInput=false;
        this.title=new MLabel({label:'',c:'#F5572A'});
        this.title.setRight();
        this.sceneGame.addChild(this.title);
        this.input=new MLabel({label:'',c:'#F5572A'});
        this.input.setLeft();
        this.sceneGame.addChild(this.input);
        this.title.setPos(this.width/2,this.height/2-wid);
        this.input.setPos(this.width/2+10,this.title.y);
    }
    setCount1(a,b,c){
        let random=Math.random();
        if(random<0.5){
            this.title.value=`${a}+${b}=`;
            this.answer=c;
        }else{
            this.title.value=`${c}-${b}=`;
            this.answer=a;
        }
        console.log(this.title.value);
    }
    enterGameNext(){
        let num=this.selectNum+1;
        let [a,b,c]=[Unify.getRandomWeiShu(num),Unify.getRandomWeiShu(num),0];
        this.input.scale=this.title.scale=2-num*0.1;
        if(this.selectNum>3){
            this.input.scale=this.title.scale=2;
        }
        switch(this.selectNum){
            case 0:
            case 1:
            case 2:
            case 3:
                c=a+b;
                this.setCount1(a,b,c);
                break;
            case 4:
            case 5:
                [a,b]=[Unify.getRandomWeiShu(1),Unify.getRandomWeiShu(1)];
                c=a*b;
                if(this.selectNum==4){
                    this.title.value=`${a}×${b}=`;
                    this.answer=c;
                }else{
                    this.title.value=`${c}÷${b}=`;
                    this.answer=a;
                }
                break;
            case 6:
            case 7:
                [a,b]=[Unify.getRandomWeiShu(1),Unify.getRandomWeiShu(2)];
                if(this.selectNum==7){
                    a=Unify.getRandomWeiShu(2);
                }
                c=a*b;
                this.title.value=`${a}×${b}=`;
                this.answer=c;  
                break;
        }
        this.showScore();
    }
    judge(){
        if(this.input.value==this.answer){
            this.addScore();
            this.enterGameNext();
            this.playSoundRight();
        }else{
            this.playSoundWrong();
        }
        this.input.value='';
    }
}
/**列算式计算*/
class ColumnCountGame extends BasicGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['一位数乘两位数','两位数乘三位数','三位数乘三位数','两位数除一位数','三位数除两位数','四位数除两位数'];
    }
    initSceneNext(){  
        this.createHomeButton(this.getLabels());
        let w=this.wid;
        let n=this.minNum;
        this.nodes=[];
        this.grids=[];
        for(let i=0;i<n;i++){
            let gs=[];
            for(let j=0;j<n;j++){
                let sprite=new MSprite();
                sprite.dr(w,w,'white',{s:0.5,c:'black'});
                this.sceneGame.addChild(sprite);
                this.nodes.push(sprite);
                gs.push(sprite);
                let label=new MLabel({label:'',c:'black'});
                label.x=w/2;
                label.y=w/2;
                sprite.addChild(label);
                sprite.label=label;
                sprite.on('click',this.onClick,this)
            }
            this.grids.push(gs);
        }
        let x=(this.width-w*n)/2;
        let y=(this.height-w*n)/2;
        Unify.displayRank(this.nodes,n,0,0,x,y);
        this.createNumKey();

        this.lineLayer=new MBasice();
        this.sceneGame.addChild(this.lineLayer);

        let names=['得数','余数'];
        this.answerInputs=[];
        let [wid,parent]=[this.wid,this.topToolBar];
        for(let i=0;i<2;i++){
            let label=new MLabel({label:names[i],c:'balck'})
            let x=wid+i*wid*4;
            let y=parent.height/2;
            label.x=x;
            label.y=y;
            parent.addChild(label);

            let node=new MSprite;
            node.dr(wid*2,wid*0.8,'white',{s:1,c:'black'});
            node.x=x+node.width/2;
            node.y=y-wid/2;
            node.on('click',this.onClick,this)
            label=new MLabel({label:'',c:'balck'})
            label.x=wid;
            label.y=node.height/2;
            node.addChild(label);
            node.label=label;
            node.name='answer';
            parent.addChild(node);
            this.answerInputs.push(label);
        }
    }
    onClick(e){
        let target=e.currentTarget;
        if(target.noClick)return;
        if(this.input){
            this.input.parent.color='white';
        }
        this.answerInputs.forEach(label=>label.parent.color='white')
        this.playSoundByCode('E3');
        target.color='yellow';
        this.input=target.label;
    }
    onInput(code){
        if(this.input.parent.name=='answer')    this.input.value+=code;
        else                                    this.input.value=code;
    }
    createLine(w,y,h=2){
        let line=new MSprite();
        line.dr(w,h,'black');
        line.y=y;
        this.lineLayer.addChild(line);
        return line;
    }
    enterGameNext(){
        this.showScore();
        this.lineLayer.removeAllChildren();
        let [ox,oy]=[this.nodes[0].x,this.nodes[0].y];
        if(this.selectNum<3){
            for(let i=0;i<2;i++){
                this.createLine(this.width,oy+2*this.wid+i*3*this.wid);
            }
        }else{
            for(let i=0;i<3;i++){
                this.createLine(this.width,oy+3*this.wid+i*2*this.wid);
            }
            ox+=4*this.wid;
            let line=this.createLine(this.wid*4,oy+this.wid);
            line.x=ox;
            line=this.createLine(2,oy+this.wid,this.wid);
            line.x=ox;
        }

        this.nodes.forEach(node=>{ node.color='white';node.label.value='';  })
        this.answerInputs[0].value=this.answerInputs[1].value='';

        let nums=[[1,2],[2,3],[3,3],[1,2],[2,3],[2,4]][this.selectNum];
        let titles=[Unify.getRandomWeiShu(nums[0]),Unify.getRandomWeiShu(nums[1])];
        if(this.selectNum<3){
            this.answer=titles[0]*titles[1];
            this.yushu=0;
            titles[0]=' '+titles[0];
            titles[1]='x'+titles[1];
            if(this.selectNum==0){
                titles[0]='  '+titles[0];
                titles[1]=' '+titles[1];
            }else if(this.selectNum==1){
                titles[0]=' '+titles[0];
            }
            for(var i=0;i<2;i++){
                let str=String(titles[i]);
                for(var j=0;j<str.length;j++){
                    var node=this.grids[i][5+j];
                    node.noClick=true;
                    var label=node.label;
                    label.value=String(str[j]);
                }
            }
        }else{
            this.answer=Math.floor(titles[1]/titles[0]);
            this.yushu=titles[1]%titles[0];
            let s=String(titles[0]);
            while(s.length<4){
                s=' '+s;
            }
            titles[0]=s;
            for(var i=0;i<2;i++){
                let str=String(titles[i]);
                for(var j=0;j<str.length;j++){
                    var node=this.grids[1][0+i*4+j];
                    node.noClick=true;
                    var label=node.label;
                    label.value=String(str[j]);
                }
            }
        }
    }
    judge(){
        let[answer,yushu]=[Number(this.answerInputs[0].value),Number(this.answerInputs[1].value)];
        let isRight=this.answer==answer&&this.yushu==yushu;
        console.log(this.answer,answer,this.yushu,yushu)
        if(isRight){
            this.addScore();
            this.enterGameNext();
            this.playSoundRight();
        }else{
            this.playSoundWrong();
        }
    }
}
/**变色球*/
class ColorBallGame extends BasicGame{
    initStart(){
        this.createScene({c3:'#999999'});
        this.createBtnClose();
        this.enterHome();
        this.initSceneNext();
    }
    getLabels(){
        return ['开始'];
    }
    initSceneNext(){  
        this.createGameBg();
        this.createHomeButton(this.getLabels());
        this.colors=['red','green','blue','yellow','violet','orange','cyan','pink'];
        this.ballColor=this.colors[2];
        this.walls=[];
        this.addBall();
        this.sceneGame.addEvent('click',this.onClick.bind(this));
        this.createText();
    }
    createText(){
        this.txtScore=new MLabel({label:''});
        this.txtScore.setPos(this.width/2-this.wid*2,this.wid/2);
        this.sceneGame.addChild(this.txtScore);

        this.txtBestScore=new MLabel({label:''});
        this.txtBestScore.setPos(this.width/2+this.wid*2,this.wid/2);
        this.sceneGame.addChild(this.txtBestScore);
    }
    createGameBg(){
        let xNum=4;
        let wid=this.width/xNum;
        let map=new MMap({color:'#99D9EA',width:wid,height:wid});
        map.setColor2('#8AC4D3');
        map.setNum(xNum,xNum*3).create('dr');
        this.sceneGame.addChild(map);
    }
    enterHomeNext(){
        this.isPlay=false;
    }
    enterGameNext(){
        this.score=-1;
        this.isPlay=true;
        this.count=4;
        this.addWall();
        this.ball.setPos(this.width/2,this.height/2);
        this.changeColor(this.ballColor);
        this.ballDa={vy:-8,vx:2,g:0.2};
        this.addScore();
    }
    addScore(s=1){
        this.score+=s;
        this.txtScore.value='当前：'+this.score;
        if(this.count<=this.colors.length){
            if(this.score>0&&this.score%5==0){
                this.addWall();
            }
        }
        if(!this.gameData.bestScore||this.score>this.gameData.bestScore){
            this.gameData.bestScore=this.score;
            this.saveData();
        }
        this.txtBestScore.value='最高：'+this.gameData.bestScore;
    }
    addWall(){
        let wid=this.wid/6;
        this.wallDa={left:wid,right:this.width-wid,top:0,bottom:this.height}
        this.walls.forEach(w=>{
            w.destroy();
            w=null;
        })
        this.walls.length=0;
        let leftNum=Math.ceil(this.count/2);
        let rightNum=this.count-leftNum;
        let t=this;
        create(this.height/leftNum,leftNum,0);
        create(this.height/rightNum,rightNum,t.width-wid);
        function create(hei,count,x){
            let walls=[];
            for(let i=0;i<count;i++){
                let sprite=new MSprite();
                sprite.index=t.walls.length;
                sprite.dr(wid,hei,t.colors[sprite.index]);
                t.sceneGame.addChild(sprite);
                t.walls.push(sprite);
                walls.push(sprite);
            }
            Unify.displayRank(walls,1,0,0,x,0);
        }
        this.count++;
        if(this.ballDa){
            this.ballDa.vx=this.count/2;
            this.ballDa.g+=0.05;
        }
        //console.log(this.ballDa);
    }
    addBall(){
        this.ball=new MSprite();
        this.ball.dc(this.wid/4,this.ballColor);
        this.ball.setPos(this.width/2,this.height/2);
        this.sceneGame.addChild(this.ball);
        this.balls=[];
        for(let i=0;i<8;i++){
            let ball=new MSprite();
            ball.dc(this.wid/4,this.ballColor);
            ball.setPos(this.width/2,this.height/2);
            //ball.setPos(Math.random()*200,Math.random()*200)
            ball.alpha=0.2//(1-(i+1)/10)*0.6;
            this.balls.unshift(ball);
            this.sceneGame.addChild(ball);
        }
    }
    onClick(){
        this.ballDa.vy=-8;
        this.playSoundByIndex(0);
    }
    randomColor(){
        let colors=[];
        let wid=this.width/2;
        this.walls.forEach(w=>{
            if(this.ball.x>wid){
                if(w.x<wid) colors.push(w.color);
            }else{
                if(wid<w.x) colors.push(w.color);
            }
        })
        this.changeColor(colors[Math.floor(Math.random()*colors.length)]);
        //console.log(colors)
    }
    changeColor(color){
        this.ball.color=color;
        this.balls.forEach(b=>{
            b.color=color;
        })
    }
    update(dt){
        if(this.isPlay){
            let {vx,vy,g}=this.ballDa;
            let {left,right}=this.wallDa;
            let ball=this.ball;
            let wid=ball.width/2;
            left+=wid;
            right-=wid;
            vy+=g;
			ball.y+=vy;
            ball.x+=vx;
            if(ball.x>right||ball.x<left){
                vx*=-1;
                this.walls.find(w=>{
                    let max=w.height/2;
                    let p2={x:w.x,y:w.y+max}
                    if(this.checkDistance(ball,p2,max)){
                        this.playSoundByIndex(w.index);
                        if(ball.color==w.color){
                            this.addScore();
                            this.randomColor();
                            return true;
                        }else{
                            this.gameOver();
                        }
                    }
                })
            }
            if(this.ball.y>this.height+this.width){
                this.gameOver();
            }
            this.ballDa.vx=vx;
            this.ballDa.vy=vy;

            Unify.snakeMove(this.balls,this.ball,2);
        }
    }
}
/**变色方块*/
class ColorBoxGame extends ColorBallGame{
    initStart(){
        this.createScene({c3:'#22B14B'});
        this.createBtnClose();
        this.enterHome();
        this.initSceneNext();
    }
    addWall(){}
    initSceneNext(){  
        this.createGameBg();
        this.createHomeButton(this.getLabels());
        this.colors=gameColors//['red','green','blue','yellow','violet','orange','cyan','pink'];
        this.createText();
    }
    enterGameNext(){
        this.count=4;
        this.score=0;
        this.ansNum=0;
        this.setBoxColor();
        this.addScore();
    }
    createGameBg(){
        let xNum=5;
        let wid=this.width/xNum;
        this.map=new MMap({color:'white',width:wid,height:wid});
        this.map.setNum(xNum,xNum).create('dr');
        this.sceneGame.addChild(this.map);
        this.map.y=(this.height-wid*xNum)/2;
        this.map.nodes.forEach(n=>n.addEvent('click',this.onClick.bind(this)));
    }
    onClick(e){
        let target=e.currentTarget;
        this.playSoundByIndex(this.index);
        MTween.set(target).go(200,{scaleX:1.1,scaleY:1.1}).go(50,{scaleX:1,scaleY:1});
        //console.log(target.answer,this.color);
        if(target.answer==this.color){
            target.color=this.color;
            target.answer=null;
            this.ansNum++;
            if(this.ansNum==this.count){
                this.nextLevel();
            }
        }else{
            this.gameOver();
        }
    }
    nextLevel(){
        this.addScore();
        this.count++;
        this.ansNum=0;
        //MUtil.warn('+1',400);
        setTimeout(()=>{
            this.clearColor();
            this.playSoundByIndex(20);
        },800)
        setTimeout(()=>{
            this.setBoxColor();
        },1600)
    }
    clearColor(type=true){
        this.map.nodes.forEach(n=>{
            n.color='white';
            if(type)n.answer=null;
        });
    }
    setBoxColor(){
        this.clearColor();
        this.index=Math.floor(Math.random()*this.colors.length);
        this.color=this.colors[this.index];
        let arr=Unify.getArrayRandomValue(this.map.nodes,this.count);
        arr.forEach(n=>{
            n.color=this.color;
            n.answer=this.color;
        });
        setTimeout(()=>{
            this.clearColor(false);
        },1500)
        this.addCover(1500)
    }
}
/**对对碰*/
class ColorSupperzzleGame extends ColorBallGame{
    initStart(){
        this.createScene({c3:'#22B14B'});
        this.createBtnClose();
        this.enterHome();
        this.initSceneNext();
    }
    addWall(){}
    initSceneNext(){  
        this.soundUrl="../rec/sound/bg/happy-1.mp3";
        this.colors=['red','green','yellow','pink','violet','orange','cyan','blue'];
        //this.createGameBg();
        this.createHomeButton(this.getLabels());
        this.createText();
        this.createOtherBtn();
        this.createDownTime();
    }
    createOtherBtn(){
        let names=['♻️','💣'];
        let pos=[this.width/2-50,50+this.width/2];
        this.otherBtns=[];
        names.forEach((n,i)=>{
            let btn=new MEmoji();
            btn.drawEmoji(n);
            btn.index=i;
            btn.setPos(pos[i],this.height-40);
            btn.addEvent('click',this.onClickChange.bind(this));
            let txt=new MLabel({label:'1'})
            btn.addChild(txt);
            txt.y=-20;
            btn.txt=txt.text;
            this.otherBtns.push(btn);
            this.sceneGame.addChild(btn);
        });
    }
    initOtherBtn(){
        if(this.otherBtns){
            this.otherBtns.forEach(b=>{
                b.txt.text='1';
            })
        }
    }
    enterHomeNext(){
        SoundFactory.remove(this.soundUrl);
    }
    enterGameNext(){
        this.count=4;
        this.score=0;
        this.ansNum=0;
        this.canMove=false;
        this.targets=[];
        this.createGameBg();
        this.checkResult();
        this.addScore();
        this.initOtherBtn();
        this.startDownTime(3,this.gameOver.bind(this));
        SoundFactory.loop(this.soundUrl);
    }
    createGameBg(){
        if(this.maps){
            this.maps.forEach(m=>{
                m.forEach(n=>{
                    n.removeFromParent(true);
                })
            })
        }
        let [xnum,ynum,wid,g]=[6,8,50,5];
        let [x,y]=[(this.width-xnum*wid)/2,(this.height-ynum*wid)/2]
        this.g=g;
        this.ynum=ynum;
        this.wid=wid;
        this.maps=[];
        this.total=6;
        this.left=x-wid/4;
        for(let i=0;i<xnum;i++){
            let ms=[];
            for(let j=0;j<ynum;j++){
                let node=this.createNode();
                ms.push(node);
            }
            this.maps.push(ms);
            Unify.displayRank(ms,1,g,g,this.left+(i*(wid+g)),y);
            this.bottom=ms[ms.length-1].y;
		}
    }
    createHead(node,number){
        if(node.head){
            node.removeChild(node.head);
        }
        let a=new MEmoji();
        a.drawAnimal(number);
        a.setScale(1.7);
        a.setAnchor(0);
        a.x=6;
        node.head=a;
        node.addChild(a);
        return a;
    }
    createNode(){
        let number=Math.floor(Math.random()*this.total)
        let node=new MSprite();
        this.sceneGame.addChild(node);
        node.drr(this.wid,this.wid,5,this.colors[number],{s:2,c:'black'});
        this.createHead(node,number);
        node.addEvent('click',this.onClick.bind(this));
        node.number=number;
        return node;
    }
    onClickChange(e){
        let target=e.currentTarget;
        if(target.txt.text=='1'){
            this.addCover(1000);
            target.txt.text='0';
            if(target.index==0){
                this.randomChangePos();
            }else{
                this.randomRemoveNode();
            }
        }else{
            MUtil.warn('次数用完');
        }
    }
    getOneArray(){
        let allArray=this.maps;
        let ones=[];
        for(var i=0;i<allArray.length;i++){
            let xArray=allArray[i];
            for(var j=0;j<xArray.length;j++){
                ones.push(xArray[j]);
            }
        }
        return ones;
    }
    randomChangePos(){
        var allArray=this.getOneArray();
        allArray=Unify.getArrayRandomValue(allArray,10);
        for(let i=0;i<allArray.length;i+=2){
            let [t1,t2]=[allArray[i],allArray[i+1]];
            this.changeArray(t1,t2);
        }
        setTimeout(()=>{this.checkResult();},300);
    }
    randomRemoveNode(){
        var allArray=this.getOneArray();
        allArray=Unify.getArrayRandomValue(allArray,10);
        for(let i=0;i<allArray.length;i+=2){
            let n=allArray[i];
            n.isRemove=1;
            MTween.set(n).go(200,{alpha:0}).start();
        }
        setTimeout(()=>{this.checkResult();},300);
    }
    onClick(e){
        let target=e.currentTarget;
        target.alpha=0.5
        let self=this;
        self.playSoundByIndex(self.targets.length);
        self.targets.push(target);
        //console.log(self.targets.length)
        if(self.targets.length==2){
            this.addCover(500,0);
            let [t1,t2]=self.targets
            self.targets.length=0;
            if(self.checkDistance(t1,t2,self.wid+10)){
                this.changeArray(t1,t2);
                setTimeout(()=>{
                    self.checkResult();
                    t1.alpha=t2.alpha=1;
                    //console.log('canMove='+self.canMove)
                    if(self.canMove){//可以移动
                        
                    }else{//不可以移动
                        this.changeArray(t1,t2);
                    }
                },250);
            }
        }
    }
    changeArray(t1,t2){
        var allArray=this.maps;
        for(var i=0;i<allArray.length;i++){
            let xArray=allArray[i];
            for(var j=0;j<xArray.length;j++){
                let t4=xArray[j];
                if(t4==t1){
                    xArray[j]=t2;
                }else if(t4==t2){
                    xArray[j]=t1;
                }
            }
        }
        let [p1,p2]=[{x:t1.x,y:t1.y},{x:t2.x,y:t2.y}];
        MTween.set(t1).go(200,{x:p2.x,y:p2.y}).start();
        MTween.set(t2).go(200,{x:p1.x,y:p1.y}).start();
    }
    /**查看结果是不是已经没有可以移动的了*/
	checkResult(){
        var allArray=this.maps;
        let len=allArray[0].length;
        for(var j=0;j<len;j++){
            let yArray=[];
            for(var i=0;i<allArray.length;i++){
                yArray.push(allArray[i][j]);
            }
            this.checkRecultNewArr(yArray);
        }
        for(var i=0;i<allArray.length;i++){
            let xArray=allArray[i];
            this.checkRecultNewArr(xArray);
        }
        this.canMove=false;
        let s=0;
        allArray.forEach(ns=>{
            ns.forEach(n=>{
                if(n.isRemove){
                    this.canMove=true;
                    s++;
                    n.head.drawEmoji('😜',1.7);
                    n.head.setAnchor(0);
                    n.color='white';
                    MTween.set(n).go(400).go(200,{alpha:0}).start();
                }
            })
        })
        if(this.canMove){
            this.addScore(s);
            this.playSoundByIndex(-1);
            setTimeout(()=>{this.initCard();},600);
            this.addCover(1000,0);
        }
    }
    initCard(){
        var allArray=this.maps;
        let needAdd=false;
        for(var i=0;i<allArray.length;i++){
            let xArray=allArray[i];
            for(var j=0;j<xArray.length;j++){
                let n=xArray[j];
                if(n.isRemove){
                    n.removeFromParent(true);
                    xArray.splice(j--,1);
                    needAdd=true;
                }
            }
            let len=xArray.length;
            for(var j=len-1;j>=0;j--){
                let n=xArray[j];
                let y=this.bottom-(this.wid+this.g)*(len-j-1);
                MTween.set(n).go(200,{y:y}).start();
            }
        }
        if(needAdd)setTimeout(()=>{this.pushCard();},300);
    }
    pushCard(){
        this.playSoundByIndex(-1);
        var allArray=this.maps;
        for(var i=0;i<allArray.length;i++){
            let xArray=allArray[i];
            if(xArray.length<this.ynum){
                for(var j=xArray.length;j<this.ynum;j++){
                    let node=this.createNode();
                    node.alpha=0;
                    xArray.unshift(node);
                }
            }
            let len=xArray.length;
            let g=(this.wid+this.g)
            for(var j=len-1;j>=0;j--){
                let n=xArray[j];
                let y=this.bottom-g*(len-j-1);
                n.y=y;
                n.x=this.left+(i*g);
                MTween.set(n).go(200,{alpha:1}).start();
            }
        }
        setTimeout(()=>{this.checkResult();},300);
    }
    checkRecultNewArr(newArray){
        let len=newArray.length;
        let canMove=false;
        //console.log(newArray)
        for(var i=0;i<len;i++){
            if(i<len-2){
                if(newArray[i].number==newArray[i+1].number&&newArray[i].number==newArray[i+2].number){
                    newArray[i].isRemove=1;
                    newArray[i+1].isRemove=1;
                    newArray[i+2].isRemove=1;
                    canMove=true;
                }
            }
        }
        return canMove;
    }
}
/**正方体的摆放*/
class CubeFreeDrag extends BasicGame{
    initStart(){
        this.createScene({c3:'#FFFFFF'});
        this.createBtnClose();
        this.enterHome();
        this.initSceneNext();
    }
    getLabels(){
        return ['开始'];
    }
    enterHomeNext(){}
    initSceneNext(){  
        this.url='../rec/graphic/cube.png';
        this.createHomeButton(this.getLabels());
        this.cubes=[];
        let btnCube=new MButton({label:'添加正方体',width:this.wid*3,height:this.wid});
        btnCube.x=(this.width-btnCube.width)/2;
        btnCube.y=this.height-100;
        btnCube.on('click',this.onClick,this);
        this.position=btnCube.getPosition();
        this.position.x-=60;
        this.sceneGame.addChild(btnCube);


        let removeBox=new MSprite();
        removeBox.addChild(new MLabel({label:'拖入删除'}).setPos(this.wid,this.wid))
        removeBox.setPos(btnCube.x+btnCube.width+10,btnCube.y-this.wid);
        removeBox.drr(this.wid*2,this.wid*2,10,'red');
        this.sceneGame.addChild(removeBox);
        this.removeBox=removeBox;
        
        let total=6;
        let layerNames=[];
        this.layers=[];
        for(let i=0;i<total;i++){
            let layer=new MBasice;
            this.sceneGame.addChild(layer);
            this.layers.unshift(layer);
            layerNames.push((i+1)+'层');
        }
        this.selIndex=total-1;

        let tc = new MToggleContainer({ type: 1 });
		tc.create(layerNames);
		tc.setPos(20, 100);
		this.sceneGame.addChild(tc);
		tc.select(this.selIndex);
		tc.addEvent(mConst.CHANGE, (e) => { this.selIndex=e.target.index});
    }
    getLayer(){
        return this.layers[this.selIndex];
    }
    onClick(e){
        var cube=new MImage({url:this.url});
        cube.setPosition(this.position);
        cube.setWH(50,50);
        cube.startDrag();
        cube.addEvent('pressup',this.mouseup.bind(this));
        var layer=this.getLayer();
        layer.addChild(cube);
    }
    mouseup(e){
        var target=e.currentTarget;
        if(Unify.posToPosDistance(target,this.removeBox)<this.wid){
            target.removeFromParent(true);
            return;
        }
        var layer=this.getLayer();
        var cubes=layer.children;
        var len=cubes.length;
        // var [mx,my]=[this.width,this.height];
        var temps=[];
        for(let i=0;i<len;i++){
            let c=cubes[i];
            temps.push(c);
            let [x,y]=[c.x,c.y];
            if(c!=target){
                if(target.x>c.x&&Unify.posToPosDistance(target,c)<50){
                    if(Math.abs(target.y-c.y)<5){
                        target.y=c.y;target.x=c.x+35;
                    }else{
                        if(target.y<c.y&&Math.hypot(target.x-x,target.y-y)<30){
                            target.x=c.x+13;
                            target.y=c.y-13;
                        }
                    }
                }
            }
            c.r=0;
            for(let j=0;j<len;j++){
                let b=cubes[j];
                if(c!=b){
                    if(c.x>b.x+10)c.r+=1;//向左加1
                    if(c.y>b.y+10)c.r+=20;//向下加20
                }
            }
            // console.log(c.r);
        }
        temps.sort((a,b)=>{return a.r-b.r});
        for(let i=0;i<len;i++){
            let c=temps[i];
            layer.addChild(c);
        }
    }
}
/**数学题*/
class MathQuestion extends BasicGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['二级年奥数','三级年奥数'];
    }
    createStarMoonSun(){}
    enterGameNext(){
        this.datas=[];
        if(this.selectNum==0)  this.datas=MathData.MO2;
        else if(this.selectNum==1)  this.datas=MathData.MO3;
        this.numPage.setTotal(this.datas.length-1);
        this.onUpdatePage();
    }
    initSceneNext(){
        this.createHomeButton(this.getLabels());

        this.datas=MathData.MO2;
        let [rad,onePage,total]=[this.wid/2,5,this.datas.length];
        let numPage=new MNumPage({radius:rad,onePage:onePage,gap:5,total:total});
		numPage.setPos((this.width-numPage.width)/2+rad*1.5, this.height-rad*4);
		numPage.addEvent(mConst.CHANGE,this.onUpdatePage.bind(this));
		this.sceneGame.addChild(numPage);
        this.numPage=numPage;

        let [wid,hei,color]=[this.width-this.wid,this.height/2,'#59DF00'];
        var bg=new MSprite();
        bg.drr(wid,hei,8,color);
        bg.setPos((this.width-wid)/2,this.height/8);
        let icon=(new MShape()).dp(10,3,color).setPos(wid,20);
        icon.rotation=-90;
        bg.addChild(icon);
        this.sceneGame.addChild(bg);
        this.txtTitle=new MLabel({label:'',c:'black'});
        this.txtTitle.setPos(wid/2,20);
        //this.txtTitle.setRight();
        bg.addChild(this.txtTitle);

        [wid,hei,color]=[this.width-this.wid,this.wid,'#ffffff'];
        var bg=new MSprite();
        bg.drr(wid,hei,8,color);
        bg.setPos((this.width-wid)/2,this.height*0.7);
        icon=(new MShape()).dp(10,3,color).setPos(0,20);
        icon.rotation=90;
        bg.addChild(icon);
        this.sceneGame.addChild(bg);
        this.txtAnswer=new MLabel({label:'',c:'black'});
        this.txtAnswer.setPos(20,hei/2);
        this.txtAnswer.setLeft();
        bg.addChild(this.txtAnswer);
        bg.addEvent(mConst.CLICK,this.onLookAnswer.bind(this));

        this.createLookAnswer();

        this.onUpdatePage();
    }
    createLookAnswer(){        
        let [wid,hei]=[this.width-this.wid,this.height/2];
        let qa=new QuestAnswer(wid, hei);
		qa.setPos((this.width-wid)/2,(this.height-hei)/2);
		qa.addEvent(mConst.COMPLETE,(e)=>{
            if(qa.isRight()){
                this.txtAnswer.value=this.answer;
            }else{
                MUtil.warn('计算错误')
            }
        })
        this.qa=qa;
        //this.addChild(this.qa);this.qa.setMul();
    }
    onLookAnswer(){
        this.qa.setMul();
        this.addChild(this.qa);
    }
    onUpdatePage(){
        let index=this.numPage.getIndex();
        console.log('现在是第'+index+'页');
        let data=this.datas[index];
        let title=data[1];
        let len=title.length;
        for(let i=0;i<len;i++){
            if(i%15==0){
                title=title.slice(0,i)+'\n'+title.slice(i);
            }
        }
        this.txtTitle.value=title;
        this.answer=data[2];
        this.txtAnswer.value='点击查看答案';
    }
}
/**摩斯码输入*/
class MorseCode extends BasicGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['打字练习','自由打字'];
    }
    createStarMoonSun(){}
    enterGameNext(){
        if(this.selectNum==0){
            this.title.visible=true;
            this.title.value='';
            this.startTime=new Date().getTime();
            let vals=Unify.getArrayRandomValue(this.words,16);
            for(let i=0;i<vals.length;i++){
                this.title.value+=vals[i];
                if(i<vals.length-1)this.title.value+=' ';
                if((i+1)%4==0){
                    this.title.value=this.subStr(this.title.value);//加入换行符时不要空格
                    this.title.value+='\n';
                }
            }
        }else if(this.selectNum==1){
            this.title.visible=false;
        }
        this.output.value=this.outValue='';
        this.clearInput();
    }
    initSceneNext(){
        this.createHomeButton(this.getLabels());

        this.words='carrot,tomato,potato,lettuce,cucumber,broccoli,onion,spinach,bell,pepper,cauliflower,celery,pumpkin,eggplant,zucchini,radish,apple,banana,orange,strawberry,grape,pineapple,watermelon,peach,pear,mango,kiwi,lemon,blueberry,raspberry,avocado';
        this.words=this.words.split(',');

        let names=['.','-'];
        let btns=[];
        let maxW=this.width/2;
        let minW=this.wid*1.5;
        let midW=this.width-minW*2;
        let len=names.length;
        for(let i=0;i<len;i++){
            let btn=new MButton({label:names[i],width:maxW,height:maxW});
            btn.setSkinColors('#27BF0D','#118DF2','#209B0B');
            btn.name=names[i];
            btn.on('click',this.onInput.bind(this));
            this.sceneGame.addChild(btn);
            btns.push(btn);
        }
        let x=-1;
        let y=(this.height-maxW-minW);
        Unify.displayRank(btns,2,1,1,x,y);

        y=this.height-minW;
        let btn=new MButton({label:'空格',width:midW,height:minW});
        btn.setSkinColors('#2196F3','#35EF14','#0D82E1');
        btn.name='space';
        btn.on('click',this.onInput.bind(this));
        btn.setPos(minW,y);
        this.sceneGame.addChild(btn);

        names=['小写','换行'];
        this.isBig=false;//是否大写字母
        btns.length=0;
        for(let i=0;i<len;i++){
            let btn=new MButton({label:names[i],width:minW,height:minW});
            btn.name=names[i];
            btn.on('click',this.onInput.bind(this));
            this.sceneGame.addChild(btn);
            btns.push(btn);
        }
        Unify.displayRank(btns,2,midW+1,1,x,y);

        y=(this.height-maxW-minW*2)-1;
        let label=new MLabel({label:'',c:'black',width:midW,height:minW});
        label.createBg('#DDDDDD');
        label.setCenter();
        label.setPos(minW,y)
        this.sceneGame.addChild(label);
        this.input=label;
        this.inValue='';
        names=['删除','清除'];
        btns.length=0;
        for(let i=0;i<len;i++){
            let btn=new MButton({label:names[i],width:minW,height:minW});
            btn.name=names[i];
            btn.on('click',this.onInput.bind(this));
            this.sceneGame.addChild(btn);
            btns.push(btn);
        }
        Unify.displayRank(btns,2,midW+1,1,x,y);

        let labHei=this.height-y+this.wid
        label=new MLabel({label:'',c:'black',width:this.width,height:labHei});
        label.createBg('white',0,false);
        label.setLeft();
        label.setPos(0,-2);
        this.sceneGame.addChild(label);
        this.output=label;
        this.outValue='';

        label=new MLabel({label:'',c:'black',width:this.width,height:labHei/2});
        label.createBg('#E6F1FD',0,false);
        label.setLeft();
        label.setPos(0,labHei/2);
        this.sceneGame.addChild(label);
        this.title=label;
    }
    clearInput(){
        this.inValue='';
        this.input.value='';
    }
    onInput(e){
        let target=e.currentTarget;
        let code=target.name;
        let names=['.','-'];
        let index=names.indexOf(code);
        this.playSoundByIndex(index>=0?index:3);
        if(names.includes(code)){
            this.inValue+=code;
            this.inputShow();
        }else if(code=='space'){
            if(!!this.input.value){
                let val=Unify.mosi(this.inValue,1);
                this.outValue+=this.toLowOrUp(val);
            }else{
                this.outValue+=' ';
            }
            this.outputShow();
            this.clearInput();
        }else if(code=='删除'){
            this.inValue=this.subStr(this.inValue);
            this.inputShow();
        }else if(code=='清除'){
            if(this.input.value==''){
                this.outValue=this.subStr(this.outValue);
            }
            this.clearInput();
            this.outputShow();
        }else if(code=='换行'){
            this.outValue+='\n'
            this.outputShow();
        }else if(code=='小写'){
            this.isBig=!this.isBig;
            target.text.text=this.isBig?'大写':'小写';
            this.inputShow();
            if(this.selectNum==0){
                this.title.value=this.toLowOrUp(this.title.value);
            }
        }
    }
    toLowOrUp(value){
        if(this.isBig) return value.toLocaleUpperCase();
        else           return value.toLocaleLowerCase();
    }
    subStr(value){
        return value.substring(0,value.length-1);
    }
    outputShow(){
        let [value,title]=[this.outValue,this.title.value];
        this.output.value=value;
        if(this.selectNum==0){
           if(title.includes(value)){
                this.output.color='green';
                if(value.length==title.length){
                    let maxTime=600000;
                    this.score=Math.floor((maxTime-(new Date().getTime()-this.startTime))/maxTime*100);
                    this.score=this.score>100?100:this.score<0?0:this.score;
                    this.gameOver();
                }
           }else{
                this.output.color='red';
           }
        }else{
            this.output.color='black';
        }
        this.output.value+='|'
    }
    inputShow(){
        let value=Unify.mosi(this.inValue,1)+this.inValue;
        this.input.value=this.toLowOrUp(value);
    }
}
/**自由的输入*/
class FreeInput extends BasicGame{
    initStart(){
        this.initScene();
    }
    getLabels(){
        return ['自由打字'];
    }
    createStarMoonSun(){}
    enterGameNext(){
        this.input.value='';
    }
    initSceneNext(){
        this.createHomeButton(this.getLabels());
        var keyboard=new MKeyboard(this.width,this.height,{c1:'#FFFFFF',c2:'#eeeeee',c3:'#dddddd',fc:'black'});
		this.sceneGame.addChild(keyboard);
		keyboard.callBack=(e)=>{
			this.playSoundByIndex(1);
		}
        var input=new MLabel({label:'',width:this.width,height:300});
		input.setLeft();
		this.sceneGame.addChild(input);
		input.y=15;
		input.x=10;
		keyboard.setInput(input);
        this.input=input;

        let names=['摩斯码','间隔-','间隔+'];
        let btns=[];
        let len=names.length;
        let wid=this.width/len;
        let hei=this.wid;
        for(let i=0;i<len;i++){
            let btn=new MButton({label:names[i],width:wid,height:hei});
            btn.setSkinColors('#27BF0D','#118DF2','#209B0B');
            btn.index=i;
            btn.on('click',this.onClick.bind(this));
            this.sceneGame.addChild(btn);
            btns.push(btn);
        }
        let x=-1;
        let y=(this.height-keyboard.height-hei-5);
        Unify.displayRank(btns,len,1,1,x,y);

        this.step=200;
        this.showStep=new MLabel({label:'1'});
        this.showStep.setPos(this.width/2,y-10);
        this.sceneGame.addChild(this.showStep);

        this.lightBox=new MSprite();
        this.lightBox.dr(this.width,this.height,'black');
        this.sceneGame.addChild(this.lightBox);
        this.lightBox.on('click',this.onClick.bind(this));
        this.lightBox.visible=false;
        this.lightBox.index=-1;
    }
    onClick(e){
        let target=e.currentTarget;
        let index=target.index;
        if(index==0){
            this.lightBox.visible=true;
            this.codes=Unify.mosi(this.input.value);
            this.codes=this.codes.replaceAll('undefined ','');
            this.codes=this.codes.split(' ');
            this.codes=this.codes.filter((item)=>{return item});
            this.cnt=0;
            this.startLight();
            //console.log(this.codes)
        }else if(index==1){
            if(this.step>200) this.step-=100;
        }else if(index==2){
            if(this.step<1000) this.step+=100;
        }else if(index==-1){
            this.lightBox.visible=false;
        }
        this.showStep.value=Math.ceil(this.step/100-1);
    }
    startLight(){
        let [cnt,codes,short]=[this.cnt,this.codes,this.step];
        let [long,wait]=[short*4,short*8];
        let box=this.lightBox;
        let that=this;
        function next(){
            //console.log(box.visible);
            if(!box.visible)return;
            if(cnt<codes.length){
                let code=codes[cnt];
                let i=0;
                function open(){
                    if(!box.visible)return;
                    let c=code[i];
                    white();
                    let time=c=='-'?long:short;
                    setTimeout(close,time);
                    that.playSoundByCode('C4',c=='-'?'4n':'32n');
                }
                function close(){
                    if(!box.visible)return;
                    black();
                    i++;
                    if(i<code.length){
                        setTimeout(open,short);
                    }else{
                        cnt++;
                        if(cnt==codes.length){
                            cnt=0;
                        }
                        setTimeout(next,wait);
                    }
                }
                open();
                function white(){box.color='white'};
                function black(){box.color='black'};
            }
        }
        next();
    }
}